package com.iss.examsys.view;

import com.iss.examsys.common.EmsConstants;
import com.iss.examsys.ejb.ExamPaperBean;
import com.iss.examsys.ejb.ModuleBean;
import com.iss.examsys.ejb.SubjectTagBean;
import com.iss.examsys.ejb.UserBean;
import com.iss.examsys.entity.ExamPaper;
import com.iss.examsys.entity.LecturerModule;
import com.iss.examsys.entity.Module;
import com.iss.examsys.entity.Question;
import com.iss.examsys.entity.Section;
import com.iss.examsys.entity.SectionQuestion;
import com.iss.examsys.entity.SectionTag;
import com.iss.examsys.entity.SubjectTag;
import com.iss.examsys.entity.User;
import com.iss.examsys.view.util.JsfUtil;
import java.io.Serializable;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import javax.ejb.EJB;
import javax.faces.context.ExternalContext;
import javax.inject.Named;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.faces.view.ViewScoped;
import javax.servlet.http.HttpServletRequest;
import org.primefaces.model.DualListModel;

@Named
@ViewScoped
public class ExamPaperView implements Serializable {

    private ExamPaper newExamPaper;
    private ExamPaper selectedExamPaper;
    private Section currentSection;   
    private List<ExamPaper> examPapers;
    private List<Module> modules;
    private List<Question> availableQuestions;
    private List<Question> selectedQuestions;
    private String examPaperName;    
    private Long moduleId;
    private List<SubjectTag> selectedSubjectTags;
    
    @EJB private ExamPaperBean examPaperBean;
    @EJB private ModuleBean moduleBean;
    @EJB private SubjectTagBean subjectTagBean;
    @EJB private UserBean userBean;

    public ExamPaperView() {
    } 

    public String getExamPaperName() {
        return examPaperName;
    }

    public void setExamPaperName(String examPaperName) {
        this.examPaperName = examPaperName;
    }   

    public Long getModuleId() {
        return moduleId;
    }

    public void setModuleId(Long moduleId) {
        this.moduleId = moduleId;
    }  

    public ExamPaper getNewExamPaper() {
        return newExamPaper;
    }

    public void setNewExamPaper(ExamPaper newExamPaper) {
        this.newExamPaper = newExamPaper;
    }

    public ExamPaper getSelectedExamPaper() {
        return selectedExamPaper;
    }

    public void setSelectedExamPaper(ExamPaper selectedExamPaper) {
        this.selectedExamPaper = selectedExamPaper;
    }

    public List<ExamPaper> getExamPapers() {
        setExamPapers(examPaperBean.findAll());
        return examPapers;
    }

    public void setExamPapers(List<ExamPaper> examPapers) {
        this.examPapers = examPapers;
    }

    public List<Module> getModules() {        
        List<Module> lecModules = getModulesForLecturer();
        if(lecModules != null) {
            setModules(lecModules);
        } else {
            setModules(moduleBean.findAllModule());
        }
        return modules;
    }

    public void setModules(List<Module> modules) {
        this.modules = modules;
    }

    public Section getCurrentSection() {
        return currentSection;
    }

    public void setCurrentSection(Section currentSection) {
        this.currentSection = currentSection;
    } 

    public List<SubjectTag> getSelectedSubjectTags() {
        return selectedSubjectTags;
    }

    public void setSelectedSubjectTags(List<SubjectTag> selectedSubjectTags) {
        this.selectedSubjectTags = selectedSubjectTags;
    }

    public List<Question> getAvailableQuestions() {        
        return availableQuestions;
    }

    public void setAvailableQuestions(List<Question> availableQuestions) {
        this.availableQuestions = availableQuestions;
    }

    public List<Question> getSelectedQuestions() {
        return selectedQuestions;
    }

    public void setSelectedQuestions(List<Question> selectedQuestions) {
        this.selectedQuestions = selectedQuestions;
    }
    
    public SelectItem[] getItemsAvailableSelectOne() {
        return getSelectModuleItems(getModules(), true);
    } 
    
    public SelectItem[] getSectionTypeItemsAvailableOne() {
        return JsfUtil.getSectionTypeItems();
    } 
    
    public void createExamPaper() {
        try {
            examPaperBean.create(newExamPaper);
            resetExamPaper();
            JsfUtil.addSuccessMessage("Exam paper has been successfully created.");
        }catch(Exception e) {
            JsfUtil.addErrorMessage("Error creating exam paper. Please try again later.");
        }   
    }
    
    public void editExamPaper() {
        if(selectedExamPaper != null) {
            System.out.println(">>> at editExamPaper... name: " + selectedExamPaper.getName() + ", deprecated: " + selectedExamPaper.getDeprecated());
            examPaperBean.edit(selectedExamPaper);
        }
    }
    
    public void resetExamPaper() {
        newExamPaper = null; 
        examPaperName = null;
        currentSection = null;
        selectedSubjectTags = null;
        selectedQuestions = null;
    }
    
    public void createBlankExamPaper() {       
        newExamPaper = new ExamPaper();    
         Collection<Section> sections = newExamPaper.getSectionCollection();
        if(sections == null)
            sections = new LinkedList<>();   
        
        newExamPaper.setSectionCollection(sections);
        createBlankSection();
    }
    
    private List<Module> getModulesForLecturer() {      
        List<LecturerModule> lecturerModules;
        List<Module> lecModules = new LinkedList<>();

        ExternalContext ctx = FacesContext.getCurrentInstance().getExternalContext();
        HttpServletRequest req = (HttpServletRequest)ctx.getRequest();
        String userId = req.getRemoteUser();
        
        User user = userBean.findByUserId(userId);
        
        if(user != null) {
            lecturerModules = user.getLecturerModuleList();
            if(lecturerModules != null) {
                for(LecturerModule lm : lecturerModules){
                    lecModules.add(lm.getModuleId());
                } 
            }
        }
        return lecModules;
    }
    
    public void createBlankSection() {
        currentSection = new Section();  
        Collection<SectionQuestion> questions = new LinkedList<>();
        currentSection.setSectionQuestionCollection(questions);
        currentSection.setExamPaperId(newExamPaper); //set parent, if not won't save section to db
        selectedSubjectTags = null;
    }
    
    public void saveCurrentExamInfo() {
        System.out.println(">>> at saveCurrentExamInfo: " );
        System.out.println("Exampaper: " + this.examPaperName);
        System.out.println("Module: " + this.moduleId);
        
        newExamPaper.setName(this.examPaperName);
        newExamPaper.setModuleId(moduleBean.findModuleById(this.moduleId));
        
        
        System.out.println("Exampaper after saved: " + this.newExamPaper.getName());
        System.out.println("Module after saved: " + this.newExamPaper.getModuleId().getName());     
    }
    
    private void addSectionTags() {  
        Collection<SectionTag> sectionTagCol = new LinkedList<>();        
        currentSection.setSectionTagCollection(null); //clear first
        
        for(SubjectTag tag : selectedSubjectTags) {
           SectionTag sectionTag = new SectionTag();
           sectionTag.setSectionId(currentSection);
           sectionTag.setTagId(tag);
           sectionTagCol.add(sectionTag);
        }
        
        currentSection.setSectionTagCollection(sectionTagCol);        
        
        System.out.println("Tags: " + JsfUtil.getCommaSeparatedTags(sectionTagCol));
    }
    
    private void addCurrentSectionToSectionCollection() {
        Collection<Section> sections = newExamPaper.getSectionCollection();
        sections.add(currentSection);
        newExamPaper.setSectionCollection(sections);
    }
        
    public void saveCurrentSection() {    
        System.out.println(">>> at saveCurrentSection: " );       
        System.out.println("Section: " + currentSection.getName() + ", " + currentSection.getType()+ ", " + currentSection.getTotalMarks()); 
        
         addSectionTags();         
            
        //Auto type section not require questions for now
        if(currentSection.getType().equals(EmsConstants.SECTION_TYPE_AUTO))  {
           addCurrentSectionToSectionCollection(); 
           createBlankSection(); //prepare for next section
        }  
        else if(currentSection.getType().equals(EmsConstants.SECTION_TYPE_MANUAL)) {
            availableQuestions = newExamPaper.getModuleId().getQuestionList(); 
        }        
    }  
    
    private boolean validateSectionTotalMarks() {
        int total = 0;
        for(Question q : selectedQuestions) {
            total += q.getMark();
        }
        
        if(total != Integer.parseInt(currentSection.getTotalMarks())) {  
            JsfUtil.addErrorMessage("Please select questions to get the section total marks of " + currentSection.getTotalMarks() +".");
            return false;
        }
        
        return true;
    }
    
    public void saveSelectedQuestions() {
        Collection<SectionQuestion> secQuestionCol = new LinkedList<>();    
        
        if(!validateSectionTotalMarks()) return;
        
        for(Question q : selectedQuestions) {
            SectionQuestion secQuestion = new SectionQuestion();
            secQuestion.setSectionId(currentSection);
            secQuestion.setQuestionId(q);
            secQuestionCol.add(secQuestion);
        }
        
        currentSection.setSectionQuestionCollection(secQuestionCol);
        addCurrentSectionToSectionCollection();
        
        System.out.println("SectionQuestion count: " + currentSection.getSectionQuestionCollection().size());
        
        createBlankSection(); //prepare for next section 
    }
    
    //autocomplete completeMethod
    public List<SubjectTag> completeSubjectTags(String query) {
        List<SubjectTag> result = new LinkedList<>();
        List<SubjectTag> tags = subjectTagBean.findAll();
        
        for(SubjectTag tag : tags) {
            if(tag.getName().toLowerCase().contains(query.toLowerCase())) {
                result.add(tag);
            }
        }        
        return (result);
    }    
     
    public void addQuestionsToCurrentSection(List<Question> questions) {
       Collection<SectionQuestion> sectionQuestions = currentSection.getSectionQuestionCollection();
       
       if(sectionQuestions == null)
           sectionQuestions = new LinkedList<>();
              
       for(Question q : questions) {
           SectionQuestion sq = new SectionQuestion();
           sq.setQuestionId(q);
           sectionQuestions.add(sq);
       }
    }
    
    public static SelectItem[] getSelectModuleItems(List<Module> entities, boolean selectOne) {
        int size = selectOne ? entities.size() + 1 : entities.size();
        SelectItem[] items = new SelectItem[size];
        int i = 0;
        if (selectOne) {
            items[0] = new SelectItem("", "---");
            i++;
        }
        for (Module x : entities) {
            items[i++] = new SelectItem(x.getId(), x.getName());
        }
        return items;
    }
    
}
